/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef OHOS_AVCONTROL_COMMAND_H
#define OHOS_AVCONTROL_COMMAND_H

/**
 * @addtogroup avsession
 * @{
 *
 * @brief 音视频媒体会话，提供系统内媒体的统一控制能力。
 *
 * 功能包括媒体会话，媒体会话管理，媒体会话控制。
 *
 * @syscap SystemCapability.Multimedia.AVSession.Core
 * @since 9
 * @version 1.0
 */

/**
 * @file avcontrol_command.h
 *
 * @brief 音视频控制指令的设置、获取、拷贝等声明。
 *
 * @since 9
 * @version 1.0
 */

#include <cinttypes>
#include <functional>
#include <string>
#include <variant>

#include "parcel.h"

namespace OHOS::AVSession {
/**
 * @brief 用于描述音视频播控命令工具类，播控命令的封装对象，支持设置和获取控制命令。
 */
class AVControlCommand : public Parcelable {
public:
    /**
     * @brief 操作指令。
     */
    enum {
        /** 无效指令，内部用于判断指令是否有效 */
        SESSION_CMD_INVALID = -1,
        /** 播放 */
        SESSION_CMD_PLAY = 0,
        /** 暂停 */
        SESSION_CMD_PAUSE = 1,
        /** 停止 */
        SESSION_CMD_STOP = 2,
        /** 播放下一首 */
        SESSION_CMD_PLAY_NEXT = 3,
        /** 播放上一首 */
        SESSION_CMD_PLAY_PREVIOUS = 4,
        /** 快进 */
        SESSION_CMD_FAST_FORWARD = 5,
        /** 快退 */
        SESSION_CMD_REWIND = 6,
        /** 跳播 */
        SESSION_CMD_SEEK = 7,
        /** 设置播放倍数 */
        SESSION_CMD_SET_SPEED = 8,
        /** 设置循环模式 */
        SESSION_CMD_SET_LOOP_MODE = 9,
        /** 收藏 */
        SESSION_CMD_TOGGLE_FAVORITE = 10,
        /** 无效指令，内部用于判断指令是否有效 */
        SESSION_CMD_MAX = 11
    };

    AVControlCommand();
    ~AVControlCommand() override;

    /**
     * @brief IPC通信数据反序列化。
     *
     * @param data 序列化对象{@link Parcel}。
     * @return 返回AVControlCommand的函数指针。
     * @see Marshalling
     * @since 9
     * @version 1.0
     */
    static AVControlCommand *Unmarshalling(Parcel &data);

    /**
     * @brief IPC通信数据序列化。
     *
     * @param parcel 保存序列化值的对象{@link Parcel}。
     * @return 成功返回true；否则，返回false。
     * @see Unmarshalling
     * @since 9
     * @version 1.0
     */
    bool Marshalling(Parcel &parcel) const override;

    /**
     * @brief 判断当前指令是否在有效范围内。
     *
     * @return 如果cmd_在有效范围内，范围在{@link #SESSION_CMD_INVALID}到@{link #SESSION_CMD_MAX}之间，
     * 返回true；否则，返回false。
     * @since 9
     * @version 1.0
     */
    bool IsValid() const;

    /**
     * @brief 设置操作指令。
     *
     * @param cmd 操作指令，范围在{@link #SESSION_CMD_INVALID}到{@link #SESSION_CMD_MAX}之间。
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @see GetCommand
     * @since 9
     * @version 1.0
     */
    int32_t SetCommand(int32_t cmd);

    /**
     * @brief 获取操作指令。
     *
     * @return 返回操作指令，范围在{@link #SESSION_CMD_INVALID}到{@link #SESSION_CMD_MAX}之间。
     * @see SetCommand
     * @since 9
     * @version 1.0
     */
    int32_t GetCommand() const;

    /**
     * @brief 设置媒体播放倍数。
     *
     * @param speed 媒体播放倍数，需大于0。
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @see GetSpeed
     * @since 9
     * @version 1.0
     */
    int32_t SetSpeed(double speed);

    /**
     * @brief 获取媒体播放倍数
     *
     * @param speed 媒体播放倍数，返回值。
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @see SetSpeed
     * @since 9
     * @version 1.0
     */
    int32_t GetSpeed(double &speed) const;

    /**
     * @brief 设置媒体跳播时间。
     *
     * @param time 媒体资源的位置，从媒体资源开头开始计算，单位为ms。取值需大于等于0。
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @see GetSeekTime
     * @since 9
     * @version 1.0
     */
    int32_t SetSeekTime(int64_t time);

    /**
     * @brief 获取媒体跳播时间。
     *
     * @param time 媒体资源的位置，从媒体资源开头开始计算，单位为ms。取值需大于等于0。
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @see SetSeekTime
     * @since 9
     * @version 1.0
     */
    int32_t GetSeekTime(int64_t &time) const;

    /**
     * @brief 设置媒体循环模式。
     *
     * @param mode 媒体循环模式，
     * 取值在 {@link AVPlaybackState#LOOP_MODE_SEQUENCE}到{@link AVPlaybackState#LOOP_MODE_SHUFFLE}之间。
     * @see GetLoopMode
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @since 9
     * @version 1.0
     */
    int32_t SetLoopMode(int32_t mode);

    /**
     * @brief 获取媒体循环模式。
     *
     * @param mode 保存媒体循环模式。
     * 取值在 {@link AVPlaybackState#LOOP_MODE_SEQUENCE}到{@link AVPlaybackState#LOOP_MODE_SHUFFLE}之间。
     * @see SetLoopMode
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @since 9
     * @version 1.0
     */
    int32_t GetLoopMode(int32_t &mode) const;

    /**
     * @brief 设置媒体id。
     *
     * @param assetId 媒体id，不可为空。
     * @see GetAssetId
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @since 9
     * @version 1.0
     */
    int32_t SetAssetId(const std::string &assetId);

    /**
     * @brief 获取媒体id。
     *
     * @param assetId 保存媒体id。
     * @see SetAssetId
     * @return 成功返回{@link #AVSESSION_SUCCESS}；失败则返回对应错误码。
     * @since 9
     * @version 1.0
     */
    int32_t GetAssetId(std::string &assetId) const;

     /**
     * @brief 命令数组，用于分布式业务，判断是否支持某个命令。
     *
     * @since 9
     * @version 1.0
     */
    const static inline std::vector<int32_t> localCapability {
        SESSION_CMD_PLAY,
        SESSION_CMD_PAUSE,
        SESSION_CMD_STOP,
        SESSION_CMD_PLAY_NEXT,
        SESSION_CMD_PLAY_PREVIOUS,
        SESSION_CMD_FAST_FORWARD,
        SESSION_CMD_REWIND,
        SESSION_CMD_SEEK,
        SESSION_CMD_SET_SPEED,
        SESSION_CMD_SET_LOOP_MODE,
        SESSION_CMD_TOGGLE_FAVORITE,
    };

private:
    /** 操作指令{@link #SESSION_CMD_INVALID}  */
    int32_t cmd_ = SESSION_CMD_INVALID;
    /** 操作指令对应的值，分别对应
     * {@link #SetLoopMode}，{@link #SetSeekTime}，{@link #SetSpeed}，{@link #SetAssetId}
     */
    std::variant<int32_t, double, int64_t, std::string> param_;
};
}
/** @} */
#endif // OHOS_AVCONTROL_COMMAND_H